home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 111_01 / filecomp.c < prev    next >
Text File  |  1985-08-19  |  8KB  |  306 lines

  1. /*
  2. HEADER:        ;
  3. TITLE:        File comparison;
  4. VERSION:    1.3;
  5. DATE:        10/02/1981;
  6.  
  7. DESCRIPTION:    "Compares two files, and prints differences.
  8.         May be used with all file types.";
  9.  
  10. KEYWORDS:    File, utility, compare;
  11. SYSTEM:        CP/M-80;
  12. FILENAME:    FILECOMP.C;
  13. WARNINGS:    "If the two files are not the same length, FILECOMP
  14.         will consider them different in every byte beyond
  15.         the point where the extra bytes appear in one of
  16.         the files";
  17. SEE-ALSO:    CUG Utilities II diskette;
  18. AUTHORS:    H. Moran, R. Hollinbeck, J. Smith;
  19. COMPILERS:    BDS C;
  20. */
  21. /*****************************************************************
  22.  
  23.     Version 1.0, 10/27/79:
  24.         H. Moran
  25.     Version 1.1, 2/13/80:
  26.         slight mod. H Moran.
  27.     Version 1.1, 10/2/81:
  28.         upgrade to v1.44 BDS C.
  29.         R. Hollinbeck
  30.     Version 1.3, 10/27/85:
  31.         changed printf format for third column
  32.         from %8b to %2x (BDS C does not recognize %b).
  33.         John M. Smith
  34.  
  35. *****************************************************************/
  36.  
  37. #include <bdscio.h>
  38.  
  39. /* : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
  40.     Macros for constant definitions
  41.    : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
  42.  
  43. #define EOFF -1        /* end of file marker returned by getc() */
  44. #define EOF 0x1A    /* ascii end of file mark */
  45. #define NOFILE -1    /* no such file indication given by fopen() */
  46.  
  47.  
  48. /*    -------------------------------------------------------
  49.  
  50.     Name:        main(argc,argv)
  51.     Result:        ---
  52.     Errors:        invocation syntax error or no such file
  53.     Globals:    ---
  54.     Macros:        TRUE,FALSE,NOFILE
  55.     Procedures:    fopen(),tolower(),bummer(),htoi(),fcompare()
  56.  
  57.     Action:        Byte by byte compare of 2 files and
  58.             print their differences on console
  59.  
  60.     ------------------------------------------------------- */
  61.  
  62.  
  63. main(argc,argv)
  64.     int argc;
  65.     char *argv[];
  66.     {
  67.     int fdin,fdout,ascii;
  68.     unsigned start_adrs,htoi();
  69.     char *ptr;
  70.     char mstbuf[BUFSIZ],chkbuf[BUFSIZ];
  71.  
  72.     ascii = FALSE;    /* assign the defaults */
  73.     start_adrs = 0;
  74.     if( argc < 3 || argc > 5 )
  75.       bummer();
  76.     else if( (fdin = fopen(argv[1],mstbuf)) == NOFILE )
  77.       printf("No such file %s\n",argv[1]);
  78.     else if( (fdout  = fopen(argv[2],chkbuf)) == NOFILE)
  79.       printf("No such file %s\n",argv[2]);
  80.     else  {
  81.       while( argc > 3 ) {
  82.         ptr = argv[--argc];
  83.         if( *ptr++ != '-' )
  84.           bummer();
  85.         switch ( tolower(*ptr++) ) {
  86.  
  87.           case 'a':    ascii = TRUE;
  88.             break;
  89.  
  90.           case 'b':    start_adrs = htoi(ptr);
  91.             break;
  92.  
  93.           default:    puts("Unrecognized option. Aborted\n\n");
  94.             bummer();
  95.           }    /* end switch */
  96.         }    /* end while */
  97.       fcompare(mstbuf,chkbuf,start_adrs,ascii);
  98.       }    /* end else */
  99.     exit();
  100.     }
  101.  
  102.  
  103. /*    -------------------------------------------------------
  104.  
  105.     Name:        fcompare(mfile,cfile,adrs,ascii)
  106.     Result:        ---
  107.     Errors:        ---
  108.     Globals:    ---
  109.     Macros:        EOFF,EOF
  110.     Procedures:    getc(),puts(),strcpy(),printf()
  111.  
  112.     Action:        compare 2 files and print their differences
  113.             on the console
  114.  
  115.     ------------------------------------------------------- */
  116.  
  117.  
  118.  
  119. fcompare(mfile,cfile,adrs,ascii)
  120.     char mfile[];        /* the input file buffer */
  121.     char cfile[];        /* the output file buffer */
  122.     unsigned adrs;        /* the address of begin of file */
  123.     int ascii;        /* flag of whether these are ascii files */
  124.     {
  125.     int mc,cc;        /* 1 char buffers */
  126.     char erflg;        /* flag that an error has occurred */
  127.     char *xl();        /* function to translate control chars */
  128.     char str1[6],str2[6];    /* temporaries for strings */
  129.     char xlate[10];    /* string used in ascii control char translation */
  130.  
  131.  
  132.     erflg = 0;
  133.     while( ! ( (mc = getc(mfile)) == EOFF || (ascii && mc == EOF)) ) {
  134.       if( (cc =getc(cfile)) == EOFF || ( ascii && cc == EOF )) {
  135.         puts("Checkfile shorter than Master file\n");
  136.         return;
  137.         }
  138.       else if( mc != cc ) {
  139.         if( ! erflg ) {
  140.           erflg = 1;
  141.           puts("\nRelative Master Check");
  142.           puts("\nAddress  File   File   Mismatch");
  143.           puts("\n-------  ----   ----   --------\n");
  144.           }    /* end if */
  145.         if( ascii )    {
  146.           strcpy(str1,xl(mc,xlate)); /* fudge because parameters are */
  147.           strcpy(str2,xl(cc,xlate)); /* evaluated before being passed */
  148.           printf("%4x     %-4s   %-4s      %2x\n",adrs,str1,str2,mc^cc);
  149.           }
  150.         else
  151.           printf("%4x     %2x     %2x        %2x\n",adrs,mc,cc,mc ^ cc);
  152.         }        /* end else if */
  153.       else
  154.         ;
  155.       adrs++;
  156.       }        /* end while */
  157.     if(! ( (cc = getc(cfile)) == EOFF || (ascii && cc == EOF) ) )
  158.       puts("Masterfile shorter than checkfile\n");
  159.     return;
  160.     }        /* end fcompare() */
  161.  
  162. /*    -------------------------------------------------------
  163.  
  164.     Name:        err_exit(msg)
  165.     Result:        ---
  166.     Errors:        ---
  167.     Globals:    ---
  168.     Macros:        ---
  169.     Procedures:    printf(),exit()
  170.  
  171.     Action:        Print a message then exit to CP/M 
  172.  
  173.     ------------------------------------------------------- */
  174.  
  175.  
  176. err_exit(msg)
  177.     char *msg;
  178.     {
  179.     exit(puts(msg));
  180.     }
  181.  
  182. /*    -------------------------------------------------------
  183.  
  184.     Name:        htoi(string)
  185.     Result:        unsigned integer value of ascii hex string
  186.     Errors:        ---
  187.     Globals:    ---
  188.     Macros:        ---
  189.     Procedures:    tolower(),isalpha(),isdigit()
  190.  
  191.     Action:        ---
  192.  
  193.     ------------------------------------------------------- */
  194.  
  195.  
  196. unsigned htoi(string)
  197.     char *string;
  198.     {
  199.     unsigned number;
  200.     char c;
  201.  
  202.     number = 0;
  203.     c = tolower(*string++);
  204.     while( isalpha(c) || isdigit(c) ) {
  205.       if( c > 'f' )
  206.         return number;
  207.       number *= 16;
  208.       if( isdigit(c) )
  209.         number += c -'0';
  210.       else
  211.         number += c - 'a' + 10;
  212.       c = tolower(*string++);
  213.       }
  214.     return number;
  215.     }
  216. /*    -------------------------------------------------------
  217.  
  218.     Name:        bummer()
  219.     Result:        ---
  220.     Errors:        ---
  221.     Globals:    ---
  222.     Macros:        ---
  223.     Procedures:    puts(),exit()
  224.  
  225.     Action:        Print the invocation syntax error message
  226.             and exit to CP/M
  227.  
  228.     ------------------------------------------------------- */
  229.  
  230.  
  231. bummer()
  232.     {
  233.     puts("Correct invocation form is:\n");
  234.     puts(" FILECOMP <master file> <check file> {-a -b<hex-num>}\n\n");
  235.     puts("Where optional arguments are:\n\n");
  236.     puts("-a          => these are ascii files (terminate on 1AH )\n");
  237.     puts("-b<hex-num> => begin of file is address <hex-num> ");
  238.     puts("default is 0\n");
  239.     exit();
  240.     }
  241.  
  242.  
  243. /*    -------------------------------------------------------
  244.  
  245.     Name:        xl(c)
  246.     Result:        pointer to  xlate[]
  247.     Errors:        ---
  248.     Globals:
  249.     Macros:        ---
  250.     Procedures:    strcpy()
  251.  
  252.     Action:        Translate the char argument c into a
  253.             4 char string in  xlate[]
  254.             If c is a printable ascii char its
  255.               translation is itself right blank padded
  256.             Else if c is a standard control char its
  257.               translation is a string identifying that
  258.               control char
  259.             Else its translation is "????"
  260.  
  261.     ------------------------------------------------------- */
  262.  
  263.  
  264. char *xl(c,xlate)
  265.     int c;
  266.     char *xlate;
  267.     {
  268.     if( c > 0x7f || c < 0 )
  269.       strcpy(xlate,"????");
  270.     else if( c == 0x7f )
  271.       strcpy(xlate,"del ");
  272.     else if( c > 0x1f ) {    /* then it is printable */
  273.       xlate[0] = c;
  274.       strcpy(xlate+1,"   ");
  275.       }
  276.     else
  277.       switch (c) {
  278.         case 0x7:    strcpy(xlate,"bel");
  279.             break;
  280.  
  281.         case 0x8:    strcpy(xlate,"bs");
  282.             break;
  283.  
  284.         case 0x9:    strcpy(xlate,"tab");
  285.             break;
  286.  
  287.         case 0xa:    strcpy(xlate,"lf");
  288.             break;
  289.  
  290.         case 0xc:    strcpy(xlate,"ff");
  291.             break;
  292.  
  293.         case 0xd:    strcpy(xlate,"cr");
  294.             break;
  295.  
  296.         case 0x1b:    strcpy(xlate,"esc");
  297.             break;
  298.  
  299.         default:    xlate[0] = '^';        /* show control chars as */
  300.             xlate[1] = c + 0x40;    /* ^ <char> e.g. ^A is */
  301.             xlate[2] = '\0';    /* control A */
  302.             break;
  303.         }
  304.     return xlate;
  305.     }
  306.